home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Typography Samples / Adjust Layout ƒ / Adjust Layout.c next >
Encoding:
C/C++ Source or Header  |  1996-06-18  |  16.5 KB  |  500 lines  |  [TEXT/KAHL]

  1. /**\
  2. |**| =====================================================================
  3. |**|
  4. |**|    Adjust Layout.c
  5. |**|
  6. |**|    This file contains the calls that this sample needs to make
  7. |**|    the QuickDraw GX shell work correctly.
  8. |**|
  9. |**|    QuickDraw GX Libraries Used:
  10. |**|    "ColorLibrary.c", "FontLibrary.c", "GraphicsDebugLibrary.c",
  11. |**|    "LayoutLibrary.c", "ShapeLibrary.c", and "TransformLibrary.c".
  12. |**|
  13. |**|    6/96 bob    Updated #includes to support changed GX Library names.
  14. |**|                Updated the copyright date.
  15. |**|
  16. |**|    ©1990 - 1996  Apple Computer, Inc.
  17. |**|    All rights reserved.
  18. |**|
  19. |**| =====================================================================
  20. \**/
  21.  
  22.  
  23. #include "QDGX shell.h"
  24. #include <GXLayout.h>
  25. #include "LayoutLibrary.h"
  26.  
  27.  
  28. // Convenient constants for simplifying the code
  29.  
  30. #define withFactor {0, -ff(4)/30}
  31. #define crossFactor {0, fixed1/3}
  32. #define glyphA 36
  33. #define glyphE (glyphA + 'E' - 'A')
  34. #define glyphJ (glyphA + 'J' - 'A')
  35. #define glyphK (glyphA + 'K' - 'A')
  36. #define glyphN (glyphA + 'N' - 'A')
  37. #define glyphU (glyphA + 'U' - 'A')
  38. #define glyphV (glyphA + 'V' - 'A')
  39. #define glyphW (glyphA + 'W' - 'A')
  40. #define glyphY (glyphW + 2)
  41. #define nAdjustments 3
  42. #define nSubstitutions 4
  43.  
  44.  
  45. /**\
  46. |**| ---------------------------------------------------------------------
  47. |**| PROTOTYPES
  48. |**| ---------------------------------------------------------------------
  49. \**/
  50.  
  51. // funtions required by shell
  52.  
  53. void    DoSetup            (void);
  54. void    DoDraw            (WindowPtr wind, Boolean updating);
  55. OSErr    DoCreateNew        (void);
  56. void    DoDispose        (WindowPtr wind);
  57. void    DoIdle            (WindowPtr wind);
  58. void    DoTeardown        (void);
  59. void    DoClick            (WindowPtr wind, Point p);
  60.  
  61. // private functions
  62.  
  63. OSErr    DoWindowInit        (WindowPtr wind);
  64. void    CreateSampleImage    (WindowPtr wind);
  65.  
  66.  
  67. /**\
  68. |**| ---------------------------------------------------------------------
  69. |**| ENUMS
  70. |**| ---------------------------------------------------------------------
  71. \**/
  72. enum { rWindResource = 128 };
  73.  
  74.  
  75. /**\
  76. |**| ---------------------------------------------------------------------
  77. |**| GLOBALS
  78. |**| ---------------------------------------------------------------------
  79. \**/
  80. // If gDebugging = TRUE, graphics library errors and notices will be posted.  This
  81. // functionality will only work with the "debugging" version of QuickDraw GX.
  82. // If the debugging version is not installed, nothing bad will happen, but these
  83. // functions will not work. 
  84.  
  85. Boolean        gDebugging = true;
  86.  
  87. // Set  "gGiveMeValidation" to TRUE if you want receive run-time validation.
  88.  
  89. Boolean        gGiveMeValidation = true;
  90.  
  91.  
  92. // gGraphicsHeapSize sets the size of the graphics heap created by calling the
  93. // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c.  You can determine
  94. // the amount of graphics heap required by using GraphicsBug.  I'm giving it 600K,
  95. // since we need abunch if we have several windows open.
  96.  
  97. long        gGraphicsHeapSize = 600;
  98.  
  99. // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
  100. // override.  This is so that our override can be native PowerPC code if necessary.
  101.  
  102. GXPrintingEventUPP    gOurPrintingOverrideUPP;
  103.  
  104.  
  105.  
  106. /**\
  107. |**| ---------------------------------------------------------------------
  108. |**| DoSetup()
  109. |**| Here's where we initialize any global variables our application needs.
  110. |**| We have only one at this time -- the universal proc pointer for
  111. |**| our printing override.
  112. |**| ---------------------------------------------------------------------
  113. \**/
  114. void DoSetup (void)
  115. {    // Initialize our printing event override UPP
  116.     gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
  117. }
  118.  
  119.  
  120. /**\
  121. |**| ---------------------------------------------------------------------
  122. |**| DoDraw()
  123. |**| Draw the contents of the window.  The first parameter is the window
  124. |**| to draw, and the second parameter is true if we're updating an existing
  125. |**| image.  If that's the case, we don't want to change anything, but
  126. |**| just draw what's already there.
  127. |**| ---------------------------------------------------------------------
  128. \**/
  129. void DoDraw (WindowPtr wind, Boolean updating)
  130. {
  131.      #pragma unused (updating)
  132.      GXDrawShape (GetDocShape(wind));
  133. }
  134.  
  135.  
  136. /**\
  137. |**| ---------------------------------------------------------------------
  138. |**| DoCreateNew()
  139. |**| This routine is called when a window needs to be created.
  140. |**| ---------------------------------------------------------------------
  141. \**/
  142. OSErr DoCreateNew (void)
  143. {
  144.     OSErr        err = noErr;
  145.     WindowPtr    wind;
  146.     
  147. // Get and create our window from the resource fork
  148.  
  149.     wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
  150.  
  151. // Attach a default gxViewPort to it, create and iInitialize our
  152. // private data for it, and add a sample image to its page shape.
  153.  
  154.     if ( wind == NULL )
  155.         return (MemError());
  156.  
  157.     GXIgnoreGraphicsNotice(transform_already_set);
  158.     SetDefaultViewPort(GXNewWindowViewPort(wind));            
  159.     GXPopGraphicsNotice();
  160.     
  161.     err = DoWindowInit(wind);
  162.     if ( err != noErr )
  163.         return err;
  164.     
  165.     CreateSampleImage(wind);
  166.     return err;
  167. }
  168.  
  169.  
  170. /**\
  171. |**| ---------------------------------------------------------------------
  172. |**| DoDispose()
  173. |**| This routine is called when a window needs to be disposed of.
  174. |**| ---------------------------------------------------------------------
  175. \**/
  176. void DoDispose (WindowPtr wind)
  177. {
  178.     TH_Doc    doc;
  179.     
  180. // You should always dispose of your GX graphics objects before tossing your window.
  181. // Why?  It's generally good form and this approach guarantees that everything is
  182. // disposed.  If you had not disposed of everything, the call to DisposeWindow should
  183. // dispose of the objects. If you are running the debugging version of QuickDraw GX
  184. // with notices set, you will receive a notice that you had not disposed of everything.
  185. // You can turn notices on in this file by setting gDebugging = TRUE (above).
  186.     
  187.     if ( wind != NULL )
  188.     {
  189.         doc = (TH_Doc)GetWRefCon(wind);        // Remember, this is where we stored our private data.
  190.         GXDisposeShape(GetDocShape(wind));     // Dispose of this doc's shape.
  191.         GXDisposeJob(GetDocJob(wind));        // Dispose of this doc's print job.
  192.         DisposHandle((Handle) doc);            // Dispose of our private data.
  193.         DisposeWindow(wind);                // Dispose of the window.
  194.     }
  195. }
  196.  
  197.  
  198. /**\
  199. |**| ---------------------------------------------------------------------
  200. |**| DoIdle()
  201. |**| This routine is called to do things while idling through the event loop.
  202. |**| ---------------------------------------------------------------------
  203. \**/
  204. void DoIdle (WindowPtr wind)
  205. {
  206. }
  207.  
  208.  
  209. /**\
  210. |**| ---------------------------------------------------------------------
  211. |**| DoTeardown()
  212. |**| This routine is called just before we quit to remove anything 
  213. |**| persistent that might have been setup by DoSetup().
  214. |**| ---------------------------------------------------------------------
  215. \**/
  216. void DoTeardown (void)
  217. {
  218.     DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
  219. }
  220.  
  221.  
  222. /**\
  223. |**| ---------------------------------------------------------------------
  224. |**| DoClick()
  225. |**| ---------------------------------------------------------------------
  226. \**/
  227. void DoClick(WindowPtr window, Point p)
  228. {
  229. }
  230.  
  231.  
  232.  
  233.  
  234.  
  235. /**\
  236. |**| ---------------------------------------------------------------------
  237. |**| DoWindowInit()
  238. |**| In this function we create and initialize the the private document
  239. |**| structure for a new window.  This structure contains the print job and
  240. |**| the shape which is drawn in the window.  We store this data in a handle
  241. |**| and hang it off the window's refCon field for easy retrieval.  By doing
  242. |**| this, rather than using globals, we can create many windows containing
  243. |**| unique print jobs and shapes.
  244. |**| ---------------------------------------------------------------------
  245. \**/
  246. OSErr DoWindowInit (WindowPtr wind)
  247. {
  248.     OSErr    err = noErr;
  249.     gxJob    docJob;
  250.     gxShape    docPage;
  251.     TH_Doc    windDoc;
  252.  
  253.  
  254. // Create the page shape. We set the unique items attribute to make sure that each item
  255. // added to the picture has a unique reference. If this attribute was not set, we would
  256. // not see all copies of anything we add to the shape multiple times -- we'd just see
  257. // the last version added.        
  258.  
  259.     docPage = GXNewShape(gxPictureType);
  260.     GXSetShapeAttributes(docPage, (GXGetShapeAttributes(docPage) | gxUniqueItemsShape));
  261.     
  262.     
  263. // Create a print job for this document.  This will be the same as the system default until
  264. // the user goes through the dialogs for Page Setup or Print…
  265.  
  266.     err = GXNewJob(&docJob);
  267.     
  268.     
  269. // If there are no errors, create a handle the size of our document structure and store
  270. // the print job and page shape in it.  Store the handle in the window's refCon field so
  271. // that we can get at it.  (Note that the utility routines "GetDocJob" and "GetDocShape"
  272. // can be used to do this easily.
  273.  
  274.     if ( err == noErr )
  275.     {
  276.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  277.  
  278.         if ( windDoc == NULL )
  279.             err = MemError();
  280.         else
  281.         {
  282.             (*windDoc)->docJob = docJob;
  283.             (*windDoc)->docPage = docPage;
  284.             SetWRefCon(wind, (long) windDoc);
  285.         }
  286.  
  287. // Now install our application override for PrintingEvent so that we can
  288. // support the new movable-modal printing dialog boxes.
  289.  
  290.         GXInstallApplicationOverride(docJob, gxPrintingEventMsg, gOurPrintingOverrideUPP);
  291.  
  292.     }
  293.  
  294.     return err;
  295. }
  296.  
  297.  
  298. /**\
  299. |**| ---------------------------------------------------------------------
  300. |**| CreateSampleImage()
  301. |**| This function creates primitive shapes and adds them to the window's page shape.
  302. |**| ---------------------------------------------------------------------
  303. \**/
  304. void CreateSampleImage (WindowPtr wind)
  305. {
  306.     Rect    ourWindowRect = wind->portRect;         // the rectangle for this window
  307.                                                     // in QuickDraw coordinates
  308.     gxShape layout;                                    // the layout shape we're building
  309.     gxShape thePage;                                // the picture shape for our window
  310.     gxRunControls controls;                            // run controls for the layout
  311.     gxLayoutOptions layoutOptions;                    // options for our layout
  312.     StyleRunOverrides overrides;                    // structure defined in layout library.h
  313.                                                     // and used in several library calls to
  314.                                                     // make working with style runs easier
  315.     gxStyle glyphStyles[3];                            // array of three different styles for
  316.                                                     // glyphs we use
  317.     // Here's the text of the three runs
  318.     
  319.     char *text1 = "Office";
  320.     char *text2 = "AWAY AND SOME ";
  321.     char *text3 = "JUNK.";
  322.     
  323.     char *textRuns[3];                                // and the array to hold them
  324.     
  325.     short level0 = 0;                                // We have to pass levels by address,
  326.                                                     // so here's a variable to hold one            
  327.     short textLengths[3];                            // array of text lengths for GXNewLayout
  328.     short totalLength;                                // sum of the text lengths
  329.     
  330. // The "glyphX" values are #define'd at the top of this file.  There are four
  331. // values in each set -- the glyph code of the first glyph, the glyph code of the
  332. // second glyph, how much with-stream kerning to apply and how much cross-stream
  333. // kerning to apply.  We're kerning with the pairs A-W, A-Y and W-A here.
  334. // Normally you would _not_ hard-code glyph codes because they can change from font
  335. // to font, but this is a demonstration, not a shipping application.  Try this on
  336. // some non-Roman fonts, or some where the glyph codes for the ASCII characters aren't
  337. // the same as their ASCII value, and you'll see strange results.
  338.     
  339.     gxKerningAdjustment adjustments[nAdjustments] = 
  340.     {{glyphA, glyphW, withFactor, crossFactor}, 
  341.      {glyphA, glyphY, withFactor, crossFactor}, 
  342.      {glyphW, glyphA, withFactor, crossFactor}};
  343.      
  344. // The gxGlyphSubstitution array lets us substitute one glyph for another by
  345. // glyph code.  Again taking the liberty of assuming glyph codes for Times Roman,
  346. // this set substitutes the second glyph in each pair for the first when the layout
  347. // shape is drawn.
  348.      
  349.     gxGlyphSubstitution substitutions[nSubstitutions] = 
  350.     {{glyphJ, glyphW},
  351.      {glyphU, glyphA},
  352.      {glyphN, glyphV},
  353.      {glyphK, glyphE}};
  354.     
  355.     gxPoint posn;                                    // The position for the layout shape
  356.  
  357.     
  358. // OK, now to work.  First, initialize the textRuns array.
  359.  
  360.     textRuns[0] = text1;
  361.     textRuns[1] = text2;
  362.     textRuns[2] = text3;
  363.     
  364.     
  365. // Next, initialize the textLengths array.  MyStrLength is in this file to avoid linking
  366. // in a huge ANSI library.
  367.     
  368.     textLengths[0] = MyStrLength (text1);
  369.     textLengths[1] = MyStrLength (text2);
  370.     textLengths[2] = MyStrLength (text3);
  371.     
  372.     
  373. // Now add them all up to get the total length.
  374.     
  375.     totalLength = textLengths[0] + textLengths[1] + textLengths[2];
  376.     
  377.     
  378. // Make default gxLayoutOptions, gxRunControls and StyleRunOverrides structures.
  379. // The library routines which initialize these default structures may be found in
  380. // layout library.c.
  381.     
  382.     InitializeLayoutOptions (&layoutOptions);
  383.     InitializeRunControls (&controls);
  384.     InitializeStyleRunOverrides (&overrides);
  385.     
  386. // Position the layout half way down the left edge of the window. Set 
  387. // the layout's width to the window's width and set the flushness to 1/2, this
  388. // will cause the layout to center in the window.
  389.  
  390.     layoutOptions.width = ff(ourWindowRect.right - ourWindowRect.left);
  391.     layoutOptions.flush = fract1/2;        // fract1 is defined in math types.h
  392.  
  393.     posn.x = 0;
  394.     posn.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2);
  395.  
  396.     
  397. // Initialize the style runs.  The first one (#0) is 60 point Times Roman.
  398. // We create the style with NewLayoutStyle, found in layout library.c
  399.  
  400.     glyphStyles[0] = NewLayoutStyle(
  401.         (char *) "\pHoefler Text",    // The gxFontName for this style
  402.         ff(60),                        // the text size in fixed point
  403.         0,                            // gxTextAttribute (none for us)
  404.         &controls,                    // run controls (none for this style)
  405.         nil,                        // run features (none right now)
  406.         0,                            // count of run features (no run features == 0)
  407.         nil);                        // style run overrides (none right now)
  408.  
  409. // Now we create the next style.  We reuse the controls and style run overrides
  410. // structures, so now we set those up for the second (#1) style.
  411.  
  412. // Initialize the run controls:
  413. // Set the cross stream shift to 30 to raise the text 30 points,
  414. // and the with stream shift to -4 to move the text 4 points
  415. // closer together than normal kerning would move it.
  416.  
  417.     controls.crossStreamShift = ff(30);
  418.     controls.beforeWithStreamShift = ff(-2);
  419.     controls.afterWithStreamShift = ff(-2);
  420.  
  421. // Now set up the style run overrides:
  422. // Set up the kerning adjustments to the array we already created, and
  423. // put the count in.  nAdjustments is #define'd in Adjust Layout Sample.h.
  424.     
  425.     overrides.kerningAdjustments = adjustments;
  426.     overrides.kerningAdjustmentsCount = nAdjustments;
  427.  
  428. // We're ready to create the second style -- 30 pt. Times Roman with kerning adjustments
  429.     
  430.     glyphStyles[1] = NewLayoutStyle(
  431.         (char *) "\pTimes Roman",    // the gxFontName
  432.         ff(30),                        // the text size
  433.         0,                            // no text attributes
  434.         &controls,                    // our run controls we initialized
  435.         nil,                        // no run features
  436.         0,                            // so the run feature count is zero
  437.         &overrides);                // and our style run overrides (kerning adjustments)
  438.     
  439. // For the third style, we reset the run controls and kerning adjustments, but now
  440. // set the glyph substitutions talked about earlier.
  441.  
  442.     controls.crossStreamShift = 0;                            // default
  443.  
  444.     overrides.kerningAdjustments = nil;                        // default
  445.     overrides.kerningAdjustmentsCount = 0;                    // default
  446.  
  447.     overrides.glyphSubstitutions = substitutions;            // our glyph subs array
  448.     overrides.glyphSubstitutionsCount = nSubstitutions;        // our glyph subs count
  449.     
  450.     
  451. // Finally, create the third style -- 60 pt. Times Roman with glyph substitutions
  452.  
  453.     glyphStyles[2] = NewLayoutStyle(
  454.         (char *) "\pTimes Roman",    // the font name
  455.         ff(60),                        // the text size
  456.         0,                            // no text attributes
  457.         &controls,                    // our run controls (default again)
  458.         nil,                        // no run features
  459.         0,                            // so the run feature count is zero
  460.         &overrides);                // and our style run overrides (glyph subs)
  461.  
  462. // Now we can build the layout and add it to our picture shape
  463.     
  464.     layout = GXNewLayout(
  465.         3,                            // count of text runs
  466.         textLengths,                // array of lengths of each run
  467.         (void *) textRuns,            // array of pointers to the text
  468.         3,                            // count of style runs
  469.         textLengths,                // array of the byte length of each style run
  470.         glyphStyles,                // the array of styles we've been constructing
  471.         1,                            // the number of levels in this layout
  472.         &totalLength,                // the length of text this level applies to (all of it)
  473.         &level0,                    // array of next levels (this could be nil, too)
  474.         &layoutOptions,                // our layout options (centered, flush 1/2, etc.)
  475.         &posn);                        // the position of the layout shape
  476.         
  477.  
  478. // Retrieve the page shape so we can add to it.
  479.  
  480.     thePage = GetDocShape(wind);
  481.     
  482. // Add the layout to the window's picture shape.  AddToShape is in shape library.c.
  483.  
  484.     AddToShape(thePage, layout);
  485.     
  486. // We're done with the layout and styles, so get rid of them
  487.  
  488.     GXDisposeShape(layout);
  489.     GXDisposeStyle(glyphStyles[0]);
  490.     GXDisposeStyle(glyphStyles[1]);
  491.     GXDisposeStyle(glyphStyles[2]);
  492.     
  493.     
  494. // Invalidate the window's portRect so that everything gets updated.
  495.     
  496.     SetPort(wind);
  497.     InvalRect(&ourWindowRect);
  498. }
  499.  
  500.